home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / util / gnu / cvs-1.11.1p1.lha / contrib / commit_prep < prev    next >
Encoding:
Text File  |  2001-05-01  |  5.4 KB  |  216 lines

  1. #! /usr/bin/perl
  2. # -*-Perl-*-
  3. #
  4. #
  5. # Perl filter to handle pre-commit checking of files.  This program
  6. # records the last directory where commits will be taking place for
  7. # use by the log_accum.pl script.  For new files, it forces the
  8. # existence of a RCS "Id" keyword in the first ten lines of the file.
  9. # For existing files, it checks version number in the "Id" line to
  10. # prevent losing changes because an old version of a file was copied
  11. # into the direcory.
  12. #
  13. # Possible future enhancements:
  14. #
  15. #    Check for cruft left by unresolved conflicts.  Search for
  16. #    "^<<<<<<<$", "^-------$", and "^>>>>>>>$".
  17. #
  18. #    Look for a copyright and automagically update it to the
  19. #    current year.  [[ bad idea!  -- woods ]]
  20. #
  21. #
  22. # Contributed by David Hampton <hampton@cisco.com>
  23. #
  24. # Hacked on lots by Greg A. Woods <woods@web.net>
  25.  
  26. #
  27. #    Configurable options
  28. #
  29.  
  30. # Constants (remember to protect strings from RCS keyword substitution)
  31. #
  32. $LAST_FILE     = "/tmp/#cvs.lastdir"; # must match name in log_accum.pl
  33. $ENTRIES       = "CVS/Entries";
  34.  
  35. # Patterns to find $Log keywords in files
  36. #
  37. $LogString1 = "\\\$\\Log: .* \\\$";
  38. $LogString2 = "\\\$\\Log\\\$";
  39. $NoLog = "%s - contains an RCS \$Log keyword.  It must not!\n";
  40.  
  41. # pattern to match an RCS Id keyword line with an existing ID
  42. #
  43. $IDstring = "\"@\\(#\\)[^:]*:.*\\\$\Id: .*\\\$\"";
  44. $NoId = "
  45. %s - Does not contain a properly formatted line with the keyword \"Id:\".
  46.     I.e. no lines match \"" . $IDstring . "\".
  47.     Please see the template files for an example.\n";
  48.  
  49. # pattern to match an RCS Id keyword line for a new file (i.e. un-expanded)
  50. #
  51. $NewId = "\"@(#)[^:]*:.*\\$\Id\\$\"";
  52.  
  53. $NoName = "
  54. %s - The ID line should contain only \"@(#)module/path:\$Name\$:\$\Id\$\"
  55.     for a newly created file.\n";
  56.  
  57. $BadName = "
  58. %s - The file name '%s' in the ID line does not match
  59.     the actual filename.\n";
  60.  
  61. $BadVersion = "
  62. %s - How dare you!!!  You replaced your copy of the file '%s',
  63.     which was based upon version %s, with an %s version based
  64.     upon %s.  Please move your '%s' out of the way, perform an
  65.     update to get the current version, and them merge your changes
  66.     into that file, then try the commit again.\n";
  67.  
  68. #
  69. #    Subroutines
  70. #
  71.  
  72. sub write_line {
  73.     local($filename, $line) = @_;
  74.     open(FILE, ">$filename") || die("Cannot open $filename, stopped");
  75.     print(FILE $line, "\n");
  76.     close(FILE);
  77. }
  78.  
  79. sub check_version {
  80.     local($i, $id, $rname, $version);
  81.     local($filename, $cvsversion) = @_;
  82.  
  83.     open(FILE, "<$filename") || return(0);
  84.  
  85.     @all_lines = ();
  86.     $idpos = -1;
  87.     $newidpos = -1;
  88.     for ($i = 0; <FILE>; $i++) {
  89.     chop;
  90.     push(@all_lines, $_);
  91.     if ($_ =~ /$IDstring/) {
  92.         $idpos = $i;
  93.     }
  94.     if ($_ =~ /$NewId/) {
  95.         $newidpos = $i;
  96.     }
  97.     }
  98.  
  99.     if (grep(/$LogString1/, @all_lines) || grep(/$LogString2/, @all_lines)) {
  100.     print STDERR sprintf($NoLog, $filename);
  101.     return(1);
  102.     }
  103.  
  104.     if ($debug != 0) {
  105.     print STDERR sprintf("file = %s, version = %d.\n", $filename, $cvsversion{$filename});
  106.     }
  107.  
  108.     if ($cvsversion{$filename} == 0) {
  109.     if ($newidpos != -1 && $all_lines[$newidpos] !~ /$NewId/) {
  110.         print STDERR sprintf($NoName, $filename);
  111.         return(1);
  112.     }
  113.     return(0);
  114.     }
  115.  
  116.     if ($idpos == -1) {
  117.     print STDERR sprintf($NoId, $filename);
  118.     return(1);
  119.     }
  120.  
  121.     $line = $all_lines[$idpos];
  122.     $pos = index($line, "Id: ");
  123.     if ($debug != 0) {
  124.     print STDERR sprintf("%d in '%s'.\n", $pos, $line);
  125.     }
  126.     ($id, $rname, $version) = split(' ', substr($line, $pos));
  127.     if ($rname ne "$filename,v") {
  128.     print STDERR sprintf($BadName, $filename, substr($rname, 0, length($rname)-2));
  129.     return(1);
  130.     }
  131.     if ($cvsversion{$filename} < $version) {
  132.     print STDERR sprintf($BadVersion, $filename, $filename, $cvsversion{$filename},
  133.                  "newer", $version, $filename);
  134.     return(1);
  135.     }
  136.     if ($cvsversion{$filename} > $version) {
  137.     print STDERR sprintf($BadVersion, $filename, $filename, $cvsversion{$filename},
  138.                  "older", $version, $filename);
  139.     return(1);
  140.     }
  141.     return(0);
  142. }
  143.  
  144. #
  145. #    Main Body    
  146. #
  147.  
  148. $id = getpgrp();        # You *must* use a shell that does setpgrp()!
  149.  
  150. # Check each file (except dot files) for an RCS "Id" keyword.
  151. #
  152. $check_id = 0;
  153.  
  154. # Record the directory for later use by the log_accumulate stript.
  155. #
  156. $record_directory = 0;
  157.  
  158. # parse command line arguments
  159. #
  160. while (@ARGV) {
  161.     $arg = shift @ARGV;
  162.  
  163.     if ($arg eq '-d') {
  164.     $debug = 1;
  165.     print STDERR "Debug turned on...\n";
  166.     } elsif ($arg eq '-c') {
  167.     $check_id = 1;
  168.     } elsif ($arg eq '-r') {
  169.     $record_directory = 1;
  170.     } else {
  171.     push(@files, $arg);
  172.     }
  173. }
  174.  
  175. $directory = shift @files;
  176.  
  177. if ($debug != 0) {
  178.     print STDERR "dir   - ", $directory, "\n";
  179.     print STDERR "files - ", join(":", @files), "\n";
  180.     print STDERR "id    - ", $id, "\n";
  181. }
  182.  
  183. # Suck in the CVS/Entries file
  184. #
  185. open(ENTRIES, $ENTRIES) || die("Cannot open $ENTRIES.\n");
  186. while (<ENTRIES>) {
  187.     local($filename, $version) = split('/', substr($_, 1));
  188.     $cvsversion{$filename} = $version;
  189. }
  190.  
  191. # Now check each file name passed in, except for dot files.  Dot files
  192. # are considered to be administrative files by this script.
  193. #
  194. if ($check_id != 0) {
  195.     $failed = 0;
  196.     foreach $arg (@files) {
  197.     if (index($arg, ".") == 0) {
  198.         next;
  199.     }
  200.     $failed += &check_version($arg);
  201.     }
  202.     if ($failed) {
  203.     print STDERR "\n";
  204.     exit(1);
  205.     }
  206. }
  207.  
  208. # Record this directory as the last one checked.  This will be used
  209. # by the log_accumulate script to determine when it is processing
  210. # the final directory of a multi-directory commit.
  211. #
  212. if ($record_directory != 0) {
  213.     &write_line("$LAST_FILE.$id", $directory);
  214. }
  215. exit(0);
  216.